package server;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import model.Archivo;
import model.Log;
import model.Servidor;
import model.Usuario;
import utils.Terminal;
import controller.ArchivoController;
import controller.LogController;
import controller.UsuarioController;
import dataBaseOperations.CrudBasic;

public class ServerController extends CrudBasic<Servidor> {

	private UsuarioController userServices;
	private ArchivoController archivoServices;
	private LogController logServices;
	private KeyFactory factory;
	private Terminal console;
	private Session session;

	public ServerController(Session session) throws Exception {
		super(session);
		this.session = session;
		console = new Terminal("Services");
		userServices = new UsuarioController(session);
		archivoServices = new ArchivoController(session);
		logServices = new LogController();
		factory = KeyFactory.getInstance("RSA", "BC");
	}

	public List<String> getKeysPath() {
		return null;
	}

	public boolean uploadFile() {
		return false;
	}

	public PublicKey getUserPublicKey(String username) throws Exception {
		console.info("Obteniendo clave publica del usuario..." + username);
		Usuario u = (Usuario) userServices.getByPK(username);
		return factory.generatePublic(new X509EncodedKeySpec(u.getPublicKey()));
	}

	public KeyPair getServerKeys() throws Exception {
		console.info("Leyendo claves del servidor...");
		Servidor server = (Servidor) getByPK(1);
		X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
				server.getPublicKey());
		PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
				server.getPrivateKey());
		console.info("Claves de servidor obtenidas!");
		return new KeyPair(factory.generatePublic(publicKeySpec),
				factory.generatePrivate(privateKeySpec));
	}

	public boolean newServer(KeyPair keys) {
		Servidor server = (Servidor) getByPK(1);
		X509EncodedKeySpec encodedPublic = new X509EncodedKeySpec(keys
				.getPublic().getEncoded());
		PKCS8EncodedKeySpec encodedPrivate = new PKCS8EncodedKeySpec(keys
				.getPrivate().getEncoded());
		if (server == null) {
			console.info("Registrando nuevo servidor...");
			server = new Servidor();
			server.setIdServidor(1);
			server.setPublicKey(encodedPublic.getEncoded());
			server.setPrivateKey(encodedPrivate.getEncoded());
			return persist(server);
		} else {
			console.info("Actualizando registro del servidor...");
			server.setPublicKey(encodedPublic.getEncoded());
			server.setPrivateKey(encodedPrivate.getEncoded());
			return update(server);
		}
	}

	public boolean deleteFile(int idFile) {
		return archivoServices.deletex(idFile);
	}

	public String getFilePath(int idFile) {
		Archivo a = (Archivo) archivoServices.getByPK(idFile);
		return a.getRutaAcceso();
	}

	@Override
	protected Class<Servidor> getClazz() {
		return Servidor.class;
	}

	public Archivo getFile(int idFile) {
		return (Archivo) archivoServices.getByPK(idFile);
	}

	public int saveArchivo(String username, String grupo, String path, int tam) {
		return archivoServices.saveArchivo(path, tam, grupo, username);
	}

	public void log(String username, int idFile, int logType) {
		Log log = new Log();
		log.setFecha(new Date());
		log.setFkArchivo(idFile);
		log.setFkUsuarioTransaccion(username);
		log.setFkTipoTransaccion(logType);
		logServices.persist(log);
	}

	public void closeSession() {
		session.close();
	}

	public boolean override(String user, String path, double tam) {
		console.info("Actualizando registro...(Sobreescribiendo)");
		Query query = session.getNamedQuery("Archivo.override");
		query.setParameter("user", user);
		query.setParameter("path", path);
		query.setParameter("tam", tam);
		query.setParameter("date", new Date());
		return query.executeUpdate() > 0;
	}
}
